import os
import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import argparse

# rsync 命令选项
RSYNC_OPTS = "-avz --checksum --update"

class SyncHandler(FileSystemEventHandler):
    """处理文件系统事件的类"""
    def __init__(self, source, destination, host, user):
        self.source = source
        self.destination = destination
        self.host = host
        self.user = user
        self.remote_path = f"{user}@{host}:{destination}"
        self.changed_files = set()  # 记录发生变化的文件
        self.sync_lock = False  # 防抖锁

    def on_modified(self, event):
        """处理文件修改事件"""
        if event.is_directory:
            return  # 忽略目录变化
        self.handle_event(event)

    def on_created(self, event):
        """处理文件创建事件"""
        if event.is_directory:
            return  # 忽略目录变化
        self.handle_event(event)

    def on_deleted(self, event):
        """处理文件删除事件"""
        if event.is_directory:
            return  # 忽略目录变化
        self.handle_event(event)

    def handle_event(self, event):
        """处理文件变化事件"""
        if self.sync_lock:
            print("Sync is already in progress. Skipping...")
            return

        file_path = event.src_path
        relative_path = os.path.relpath(file_path, self.source)
        self.changed_files.add(relative_path)
        print(f"Detected change: {file_path}")
        self.trigger_sync()

    def trigger_sync(self):
        """触发同步操作"""
        if not self.changed_files:
            return

        self.sync_lock = True
        print("Starting sync...")
        self.sync_changed_files()
        self.changed_files.clear()  # 清空已同步的文件列表
        self.sync_lock = False
        print("Sync completed.")

    def sync_changed_files(self):
        """仅同步发生变化的文件"""
        for relative_path in self.changed_files:
            local_file = os.path.join(self.source, relative_path)
            remote_file = os.path.join(self.destination, relative_path)

            # 同步本地到远程
            print(f"Syncing {local_file} to remote...")
            if not self.run_rsync(local_file, f"{self.user}@{self.host}:{remote_file}"):
                print(f"Failed to sync {local_file} to remote.")
                continue

            # 同步远程到本地
            print(f"Syncing {remote_file} to local...")
            if not self.run_rsync(f"{self.user}@{self.host}:{remote_file}", local_file):
                print(f"Failed to sync {remote_file} to local.")
                continue

    def run_rsync(self, source, destination):
        """运行 rsync 命令"""
        command = f"rsync {RSYNC_OPTS} {source} {destination}"
        print(f"Executing: {command}")
        result = subprocess.run(command, shell=True, capture_output=True, text=True)
        if result.returncode == 0:
            print("Sync successful.")
        else:
            print(f"Sync failed: {result.stderr}")
        return result.returncode == 0

    def initial_sync(self):
        """执行初始化同步"""
        print("Starting initial full sync...")
        # 同步本地到远程
        if not self.run_rsync(self.source, self.remote_path):
            print("Initial sync failed.")
            return False

        # 同步远程到本地
        if not self.run_rsync(self.remote_path, self.source):
            print("Initial sync failed.")
            return False

        print("Initial full sync completed successfully.")
        return True


def main():
    parser = argparse.ArgumentParser(description="双向同步文件夹并实时监控文件变化")
    parser.add_argument("source", help="本地文件夹路径")
    parser.add_argument("destination", help="远程文件夹路径")
    parser.add_argument("--host", help="远程主机地址", required=True)
    parser.add_argument("--user", help="远程主机用户名", required=True)
    parser.add_argument("--initial-sync", action="store_true", help="执行初始化同步")
    args = parser.parse_args()

    source = args.source
    destination = args.destination
    host = args.host
    user = args.user
    initial_sync = args.initial_sync

    # 初始化事件处理器
    event_handler = SyncHandler(source, destination, host, user)

    # 执行初始化同步（如果指定）
    if initial_sync:
        if not event_handler.initial_sync():
            print("Initialization sync failed. Exiting.")
            return

    # 启动实时监控
    observer = Observer()
    observer.schedule(event_handler, source, recursive=True)
    print(f"Starting file sync and monitoring for {source}...")
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == "__main__":
    main()